home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / GDIDIB.PAK / DIBUTIL.C < prev    next >
C/C++ Source or Header  |  1997-05-06  |  17KB  |  545 lines

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993 - 1995  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE:   dibutil.c
  9. //
  10. //  PURPOSE:  Routines for processing DIBs.
  11. //
  12. //  FUNCTIONS:
  13. //    DIBError          - Displays a message box with error message
  14. //    FindDIBBits       - Sets a pointer to the DIB bits
  15. //    DIBHeight         - Gets the height of the DIB
  16. //    PaletteSize       - Calculates the buffer size required by a palette
  17. //    DIBNumColors      - Calculates number of colors in the DIB's color table
  18. //    CreateDIBPalette  - Creates a palette from a DIB
  19. //    PaintBitmap       - Paints a bitmap into a DC
  20. //    FillColorTable    - Fill color table of a DIB using system palette entries
  21. //
  22. //  COMMENTS:
  23. //    These routines are taken from the WINCAP32 sample
  24. //
  25.  
  26. #include <windows.h>
  27. #include <windowsx.h>
  28.  
  29. #include <stdio.h>
  30. #include <math.h>
  31.  
  32. #include "globals.h"  
  33. #include "resource.h"
  34. #include "palette.h"
  35. #include "dibutil.h"
  36.  
  37.  
  38. //
  39. //  FUNCTION: DIBError(int)
  40. //
  41. //  PURPOSE:  Displays a messasge box with error message
  42. //
  43. //  PARAMETERS:
  44. //    nErrNo    - 
  45. //
  46. //  RETURN VALUE:
  47. //    none.
  48. //
  49. //  COMMENTS:
  50. //
  51. //
  52. //
  53. void DIBError(int nErrNo)
  54. {
  55.     char szBuffer[40];
  56.     
  57.     if ((nErrNo < ERR_MIN) || (nErrNo >= ERR_MAX))
  58.         nErrNo = ERR_UNDEFINEDERROR;
  59.         
  60.     LoadString(hInst, nErrNo, szBuffer, sizeof(szBuffer));
  61.     MessageBox(NULL, szBuffer, szAppName, MB_OK | MB_ICONHAND);   
  62. }
  63.  
  64.  
  65. //
  66. //  FUNCTION: FindDIBBits(LPSTR)
  67. //
  68. //  PURPOSE:  Calculates the address of the DIB's bits and returns a
  69. //            pointer to the DIB bits.
  70. //
  71. //  PARAMETERS:
  72. //    LPSTR    - pointer to the DIB bits in packed-DIB memory block
  73. //
  74. //  RETURN VALUE:
  75. //    TRUE  - Success
  76. //    FALSE - Initialization failed
  77. //
  78. //  COMMENTS:
  79. //
  80. //
  81. //
  82. LPSTR FindDIBBits(LPSTR lpDIB)
  83. {
  84.    return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB));
  85. }
  86.  
  87. //
  88. //  FUNCTION: DIBHeight(LPSTR)
  89. //
  90. //  PURPOSE:  gets the height of the DIB from the BITMAPINFOHEADER height 
  91. //            field if it is a Windows 3.0-style DIB or from the 
  92. //            BITMAPCOREHEADER height field if it is an OS/2-style DIB.
  93. //
  94. //  PARAMETERS:
  95. //    lpDIB      - pointer to packed-DIB memory block
  96. //
  97. //  RETURN VALUE:
  98. //    The height of the DIB
  99. //
  100. //  COMMENTS:
  101. //
  102. //
  103. //
  104. DWORD DIBHeight(LPSTR lpDIB)
  105. {
  106.    LPBITMAPINFOHEADER   lpbih;  // pointer to a Win 3.0-style DIB
  107.    LPBITMAPCOREHEADER   lpbmc;  // pointer to an OS/2-style DIB
  108.  
  109.    // point to the header (whether OS/2 or Win 3.0
  110.  
  111.    lpbih = (LPBITMAPINFOHEADER)lpDIB;
  112.    lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  113.  
  114.     // return the DIB height if it is a Win 3.0 DIB
  115.     if (lpbih->biSize == sizeof(BITMAPINFOHEADER))
  116.         return lpbih->biHeight;
  117.     else  // it is an OS/2 DIB, so return its height
  118.         return (DWORD)lpbmc->bcHeight;
  119. }
  120.  
  121.       
  122. //
  123. //  FUNCTION: PaletteSize(LPSTR)
  124. //
  125. //  PURPOSE: 
  126. //    Gets the size required to store the DIB's palette by multiplying the 
  127. //    number of colors by the size of an RGBQUAD (for a Windows 3.0-style
  128. //    DIB) or by the size of an RGBTRIPLE (for an OS/2-style DIB).
  129. //
  130. //  PARAMETERS:
  131. //    lpDIB      - pointer to packed-DIB memory block
  132. //
  133. //  RETURN VALUE:
  134. //    The size of the color palette of the DIB
  135. //
  136. //  COMMENTS:
  137. //
  138. //
  139. //
  140. WORD PaletteSize(LPSTR lpDIB)
  141. {
  142.     // calculate the size required by the palette
  143.     if (IS_WIN30_DIB(lpDIB))
  144.           return (WORD)(DIBNumColors(lpDIB) * sizeof(RGBQUAD));
  145.      else
  146.           return (WORD)(DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));
  147. }
  148.  
  149.  
  150. //
  151. //  FUNCTION: DIBNumColors(LPSTR)
  152. //
  153. //  PURPOSE:  Calculates the number of colors in the DIB's color table
  154. //            by finding the bits per pixel for the DIB (whether Win3.0 or 
  155. //            OS/2-style DIB). If bits per pixel is 1: colors = 2, if 4: 
  156. //            colors = 16, if 8: colors = 256, if 16 or 24, no colors in 
  157. //            color table.
  158. //
  159. //  PARAMETERS:
  160. //    lpDIB      - pointer to packed-DIB memory block
  161. //
  162. //  RETURN VALUE:
  163. //    The number of colors in the color table
  164. //
  165. //  COMMENTS:
  166. //
  167. //
  168. //
  169. WORD DIBNumColors(LPSTR lpDIB)
  170. {
  171.     WORD wBitCount;  // DIB bit count
  172.  
  173.     // If this is a Windows-style DIB, the number of colors in the
  174.     // color table can be less than the number of bits per pixel
  175.     // allows for (i.e. lpbih->biClrUsed can be set to some value).
  176.     // If this is the case, return the appropriate value.
  177.     
  178.  
  179.     if (IS_WIN30_DIB(lpDIB))
  180.     {
  181.         DWORD dwClrUsed;
  182.  
  183.         dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed;
  184.         if (dwClrUsed)
  185.  
  186.         return (WORD)dwClrUsed;
  187.     }
  188.  
  189.     // Calculate the number of colors in the color table based on
  190.     // the number of bits per pixel for the DIB.
  191.     
  192.     if (IS_WIN30_DIB(lpDIB))
  193.         wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;
  194.     else
  195.         wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
  196.  
  197.     // return number of colors based on bits per pixel
  198.  
  199.     switch (wBitCount)
  200.     {
  201.         case 1:
  202.             return 2;
  203.  
  204.         case 4:
  205.             return 16;
  206.  
  207.         case 8:
  208.             return 256;
  209.  
  210.         default:
  211.             return 0;
  212.     }
  213. }
  214.  
  215.  
  216. //
  217. //  FUNCTION: CreateDIBPalette(HDIB)
  218. //
  219. //  PURPOSE: Creates a palette from a DIB by allocating memory for the
  220. //           logical palette, reading and storing the colors from the DIB's 
  221. //           color table into the logical palette, creating a palette from 
  222. //           this logical palette, and then returning the palette's handle. 
  223. //           This allows the DIB to be displayed using the best possible 
  224. //           colors (important for DIBs with 256 or more colors).
  225. //
  226. //  PARAMETERS:
  227. //    hDIB        - specifies the DIB
  228. //
  229. //  RETURN VALUE:
  230. //    A handle to the palette
  231. //
  232. //  COMMENTS:
  233. //
  234. //
  235. //
  236. HPALETTE CreateDIBPalette(HDIB hDIB)
  237. {
  238.     LPLOGPALETTE        lpPal;          // pointer to a logical palette
  239.     HANDLE              hLogPal;        // handle to a logical palette
  240.     HPALETTE            hPal = NULL;    // handle to a palette
  241.      int                 i;              // loop index
  242.      WORD                wNumColors;     // number of colors in color table
  243.      LPSTR               lpbih;          // pointer to packed-DIB
  244.      LPBITMAPINFO        lpbi;           // pointer to BITMAPINFO structure (Win3.0)
  245.      LPBITMAPCOREINFO    lpbmc;          // pointer to BITMAPCOREINFO structure (OS/2)
  246.      BOOL                fWinStyleDIB;   // Win3.0 DIB?
  247.  
  248.      // if handle to DIB is invalid, return NULL
  249.      if (!hDIB)
  250.           return NULL;
  251.  
  252.     // lock DIB memory block and get a pointer to it
  253.     lpbih = GlobalLock(hDIB);
  254.  
  255.     // get pointer to BITMAPINFO (Win 3.0)
  256.     lpbi = (LPBITMAPINFO)lpbih;
  257.  
  258.     // get pointer to BITMAPCOREINFO (OS/2 1.x)
  259.     lpbmc = (LPBITMAPCOREINFO)lpbi;
  260.  
  261.     // get the number of colors in the DIB
  262.     wNumColors = DIBNumColors(lpbih);
  263.  
  264.     // is this a Win 3.0 DIB?
  265.     fWinStyleDIB = IS_WIN30_DIB(lpbih);
  266.     if (wNumColors)
  267.     {
  268.         // allocate memory block for logical palette
  269.         hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) +
  270.                 sizeof(PALETTEENTRY) * wNumColors);
  271.  
  272.         // if not enough memory, clean up and return NULL
  273.         if (!hLogPal)
  274.         {
  275.             GlobalUnlock(hDIB);
  276.             return NULL;
  277.         }
  278.  
  279.         // lock memory block and get pointer to it
  280.         lpPal = (LPLOGPALETTE)GlobalLock(hLogPal);
  281.  
  282.         // set version and number of palette entries
  283.         lpPal->palVersion = PALVERSION;
  284.           lpPal->palNumEntries = wNumColors;
  285.  
  286.         // store RGB triples (if Win 3.0 DIB) or RGB quads (if OS/2 DIB)
  287.         // into palette        
  288.         for (i = 0; i < wNumColors; i++)
  289.         {
  290.             if (fWinStyleDIB)
  291.             {
  292.                 lpPal->palPalEntry[i].peRed = lpbi->bmiColors[i].rgbRed;
  293.                 lpPal->palPalEntry[i].peGreen = lpbi->bmiColors[i].rgbGreen;
  294.                 lpPal->palPalEntry[i].peBlue = lpbi->bmiColors[i].rgbBlue;
  295.                 lpPal->palPalEntry[i].peFlags = 0;
  296.             }
  297.             else
  298.             {
  299.                 lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
  300.                 lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
  301.                 lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
  302.                 lpPal->palPalEntry[i].peFlags = 0;
  303.             }
  304.         }
  305.  
  306.         // create the palette and get handle to it
  307.         hPal = CreatePalette(lpPal);
  308.  
  309.         // if error getting handle to palette, clean up and return NULL
  310.         if (!hPal)
  311.         {
  312.             GlobalUnlock(hLogPal);
  313.             GlobalFree(hLogPal);
  314.             return NULL;
  315.         }
  316.     }
  317.  
  318.     // clean up
  319.     GlobalUnlock(hLogPal);
  320.     GlobalFree(hLogPal);
  321.     GlobalUnlock(hDIB);
  322.  
  323.     // return handle to DIB's palette
  324.     return hPal;
  325. }
  326.  
  327.  
  328. //
  329. //  FUNCTION: PaintBitmap(HDC, LPRECT, HBITMAP, LPRECT, HPALETTE)
  330. //
  331. //  PURPOSE:  Paint a device-dependent bitmap (DDB) to the specified
  332. //            location on the specified device. 
  333. //
  334. //  PARAMETERS:
  335. //    hDC           - DC to perform output to
  336. //    lpDCRect      - rectangle on DC to perform output to
  337. //    hDDB          - handle to device-dependent bitmap (DDB)
  338. //    lpDDBRect     - rectangle of DDB to output into lpDCRect
  339. //    hPal          - handle to the palette to use with hDDB
  340. //
  341. //  RETURN VALUE:
  342. //    TRUE if bitmap was drawn, FALSE otherwise
  343. //
  344. //  COMMENTS:
  345. //    Painting routine for a DDB.  Calls BitBlt() or StretchBlt() to paint 
  346. //    the DDB.  The DDB is output to the specified DC, at the coordinates 
  347. //    given in lpDCRect.  The area of the DDB to be output is given by 
  348. //    lpDDBRect.  The specified palette is used.
  349. //
  350. //    This function always selects the palette as background. Before
  351. //    calling this function, be sure your palette is selected to desired
  352. //    priority (foreground or background).
  353. //
  354. //
  355. BOOL PaintBitmap(HDC hDC, LPRECT lpDCRect, HBITMAP hDDB,  LPRECT lpDDBRect, 
  356.         HPALETTE hPal)
  357. {
  358.     HDC         hMemDC;            // Handle to memory DC
  359.     HBITMAP     hOldBitmap;        // Handle to previous bitmap
  360.     HPALETTE    hOldPal1 = NULL;   // Handle to previous palette
  361.     HPALETTE    hOldPal2 = NULL;   // Handle to previous palette
  362.      BOOL        fSuccess;          // Success/fail flag
  363.  
  364.     // Create a memory DC
  365.     hMemDC = CreateCompatibleDC(hDC);  
  366.     if (!hMemDC)
  367.         return FALSE;
  368.  
  369.     // If we have a palette, select and realize it
  370.     if (hPal)
  371.     {
  372.         hOldPal1 = SelectPalette(hDC, hPal, FALSE); 
  373.         RealizePalette(hDC);
  374.         hOldPal2 = SelectPalette(hMemDC, hPal, FALSE);        
  375.     }
  376.  
  377.     // Select bitmap into the memory DC
  378.     hOldBitmap = SelectObject(hMemDC, hDDB);
  379.  
  380.     // Make sure to use the stretching mode best for color pictures
  381.     SetStretchBltMode(hDC, COLORONCOLOR);
  382.  
  383.     // Determine whether to call StretchBlt() or BitBlt()
  384.     if ((RECTWIDTH(lpDCRect)  == RECTWIDTH(lpDDBRect)) &&
  385.             (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDDBRect)))
  386.         fSuccess = BitBlt(hDC, 
  387.                 lpDCRect->left, 
  388.                 lpDCRect->top,
  389.                 RECTWIDTH(lpDCRect), 
  390.                 RECTHEIGHT(lpDCRect), 
  391.                 hMemDC, 
  392.                 lpDDBRect->left,
  393.                 lpDDBRect->top, 
  394.                 SRCCOPY);
  395.     else
  396.         fSuccess = StretchBlt(hDC, 
  397.                 lpDCRect->left,  
  398.                 lpDCRect->top, 
  399.                 RECTWIDTH(lpDCRect), 
  400.                 RECTHEIGHT(lpDCRect),
  401.                 hMemDC, 
  402.                 lpDDBRect->left, 
  403.                 lpDDBRect->top,  
  404.                 RECTWIDTH(lpDDBRect),
  405.                 RECTHEIGHT(lpDDBRect), 
  406.                 SRCCOPY);
  407.  
  408.     // Clean up
  409.     SelectObject(hMemDC, hOldBitmap);
  410.  
  411.     if (hOldPal1)
  412.         SelectPalette(hDC, hOldPal1, FALSE);
  413.  
  414.     if (hOldPal2)
  415.         SelectPalette(hMemDC, hOldPal2, FALSE);
  416.  
  417.     DeleteDC(hMemDC);
  418.  
  419.     // Return with success/fail flag
  420.     return fSuccess;
  421. }
  422.  
  423. //
  424. //  FUNCTION: FillColorTable(HWND, LPRGBQUAD, HPALETTE, int)
  425. //
  426. //  PURPOSE:  Fill the color table of a DIB using entries from a 
  427. //            logical palette
  428. //
  429. //  PARAMETERS:
  430. //    hWnd          - Handle to application window
  431. //    lpColorTable  - Pointer to the color table
  432. //    hPal          - Handle to palette for filling color table
  433. //    nColorsNeeded - Number of colors needed in color table
  434. //
  435. //  RETURN VALUE:
  436. //    The number of color table entries filled.
  437. //
  438. //  COMMENTS: If a palette is provided, it must be an identity
  439. //    palette with entries 0 - 9 and 246 - 255 containing the static
  440. //    VGA colors for the color table of 1, 4 and 8bpp images to be
  441. //    correct.
  442. //
  443. //
  444. int FillColorTable(HWND hWnd, LPRGBQUAD lpColorTable, HPALETTE hPal,
  445.     int nColorsNeeded)
  446. {                                                      
  447.     int nPalEntries = 0;         // number of entries in palette
  448.     HLOCAL     hLogPal;          // handle to temporary logical palette
  449.     LOGPALETTE *pLogPal;         // pointer to temporary logical palette
  450.     LPPALETTEENTRY lpPalEntries; // pointer to palette entries in log palette    
  451.     int nColors;                 // number of colors copied into color table
  452.     int i;
  453.     HDC hdc;  
  454.    
  455.     // be sure input parameters are valid
  456.     if (!lpColorTable)    
  457.         return 0;
  458.  
  459.     if (nColorsNeeded < 2 || nColorsNeeded > 256)
  460.         return 0;
  461.  
  462.     if (nColorsNeeded == 2)
  463.     {
  464.         // do color table for 1bpp
  465.         // the first RGBQUAD is already 0,0,0,0 so point to second RGBQUAD
  466.         LPRGBQUAD lpCT = lpColorTable + 1;
  467.         lpCT->rgbRed = lpCT->rgbGreen = lpCT->rgbBlue  = 255;  
  468.         return 2;
  469.     }
  470.    
  471.     hdc = GetDC(hWnd);
  472.  
  473.     if (hPal)   
  474.         // get number of entries in palette
  475.         GetObject(hPal, sizeof(int), (LPVOID)&nPalEntries);
  476.     else       
  477.         // use 256 entries in color table unless running VGA
  478.         nPalEntries = min(256, GetDeviceCaps(hdc, NUMCOLORS));
  479.                  
  480.     // create a logical palette to store the palette entries in
  481.     // so we can assign the color values to the color table quickly
  482.     hLogPal = LocalAlloc(LHND,
  483.                          sizeof(LOGPALETTE) +
  484.                          (sizeof(PALETTEENTRY) * nPalEntries));
  485.     
  486.     // get a pointer to the logical palette                     
  487.     pLogPal = (LOGPALETTE *)LocalLock(hLogPal);        
  488.    
  489.     // get a pointer to the palette entries
  490.     lpPalEntries = (LPPALETTEENTRY)(pLogPal->palPalEntry);
  491.                  
  492.     // retrieve the palette entries
  493.     if (hPal)
  494.         // use the provided palette
  495.         GetPaletteEntries(hPal, 0, nPalEntries, lpPalEntries);
  496.     else
  497.         // use the system palette
  498.         GetSystemPaletteEntries(hdc, 0, nPalEntries, lpPalEntries);
  499.  
  500.     // number of colors can't exceed size of logical palette
  501.     nColors = min(nPalEntries, nColorsNeeded);
  502.     if (nColors < 16)
  503.     {
  504.         OutputDebugString("FillColorTable: Palette is too small\r\n");
  505.         return 0;
  506.     }
  507.     
  508.     if (nColors == 16)
  509.     {
  510.         // get first 8 colors
  511.         for (i = 0; i < 8; i++, lpColorTable++, lpPalEntries++)
  512.         {
  513.             lpColorTable->rgbRed   = lpPalEntries->peRed;     
  514.             lpColorTable->rgbGreen = lpPalEntries->peGreen;
  515.             lpColorTable->rgbBlue  = lpPalEntries->peBlue;      
  516.         }
  517.  
  518.         // get the last 8 colors
  519.         for (lpPalEntries += nPalEntries - 16; i < 16; 
  520.                 i++, lpColorTable++, lpPalEntries++)
  521.         {
  522.             lpColorTable->rgbRed   = lpPalEntries->peRed;     
  523.             lpColorTable->rgbGreen = lpPalEntries->peGreen;
  524.             lpColorTable->rgbBlue  = lpPalEntries->peBlue;      
  525.         }
  526.     }
  527.     else
  528.     {    
  529.         // fill the color table as much as we can                                                           
  530.         for (i = 0; i < nColors; i++, lpColorTable++, lpPalEntries++)
  531.         {
  532.             lpColorTable->rgbRed   = lpPalEntries->peRed;     
  533.             lpColorTable->rgbGreen = lpPalEntries->peGreen;
  534.             lpColorTable->rgbBlue  = lpPalEntries->peBlue;      
  535.         }
  536.     }
  537.  
  538.     // clean up
  539.     GlobalUnlock(hLogPal);
  540.     GlobalFree(hLogPal);
  541.     ReleaseDC(hWnd, hdc);
  542.  
  543.     return nColors;
  544. }
  545.